#include <iostream>
#include <thread>
#include <chrono>

#include "executor.h"

#include "actions/sleep_action.h"
#include "actions/nondelay_action.h"

using namespace std;
using namespace action;

int main() {
  Executor exec;

  exec.setAllFinishedCallback([] { cout << "== all action done ==" << endl; });
  exec.setActionStartedCallback([](ActionId id) { cout << "== action " << id << " started ==" << endl; });
  exec.setActionFinishedCallback([](ActionId id) { cout << "== action " << id << " finished ==" << endl; });

  exec.append(new SleepAction(5));
  exec.append(new NondelayAction([] { cout << "== step1 ==" << endl; }));
  exec.append(new SleepAction(1000));
  exec.append(new NondelayAction([] { cout << "== step2 ==" << endl; }));
  auto tobe_cancel = exec.append(new NondelayAction([] { cout << "== should not see this ==" << endl; }));
  exec.append(new NondelayAction([] { cout << "== step3 ==" << endl; }));

  bool stop = false;
  for (int i = 1; !stop; ++i) {
    this_thread::sleep_for(chrono::seconds(1));
    cout << "tick: " << i << endl;
    exec.onEvent(EventId::kTimerTick);

    if (i == 7) {
      exec.cancel(tobe_cancel);
      exec.skip();
    }

    if (i == 10) {
      exec.append(new SleepAction(5));
      exec.append(new NondelayAction([] { cout << "== step4 ==" << endl; }));
    }

    if (i == 20) {
      exec.append(new SleepAction(2));
      exec.append(new NondelayAction([&] {
        cout << "== done ==" << endl;
        stop = true;
      }));
    }
  }

  return 0;
}
